package com.yilin.tms.capital.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yilin.tms.capital.mapper.StatisticsMapper;
import com.yilin.tms.capital.mapper.TradeRecordMapper;
import com.yilin.tms.capital.service.IBankCardService;
import com.yilin.commons.exception.BusinessException;
import com.yilin.commons.util.*;
import com.yilin.tms.capital.service.ITradeRecordService;
import com.yilin.tms.core.application.ReturnData;
import com.yilin.tms.core.commons.utils.ParamUtil;
import com.yilin.tms.core.commons.utils.QueryUtil;
import com.yilin.tms.core.entity.capital.BankCard;
import com.yilin.tms.core.entity.order.payment.OrderRefundCost;
import com.yilin.tms.core.entity.order.payment.ServicePaymentCost;
import com.yilin.tms.core.application.PageData;
import com.yilin.tms.core.entity.capital.TradeRecord;
import com.yilin.tms.core.entity.order.payment.OrderPaymentCost;
import com.yilin.tms.core.entity.order.payment.OrderSettlementCost;
import com.yilin.tms.core.entity.user.RoleType;
import com.yilin.tms.core.entity.user.UserType;
import com.yilin.tms.core.entity.user.account.Account;
import com.yilin.tms.core.remote.IOrderRemote;
import com.yilin.tms.core.remote.IUserRemote;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class TradeRecordService extends ServiceImpl<TradeRecordMapper, TradeRecord> implements ITradeRecordService {
    @Resource
    IOrderRemote orderRemote;

    @Resource
    TradeRecordMapper tradeRecordMapper;
    @Resource
    StatisticsMapper statisticsMapper;
    @Resource
    IBankCardService bankCardService;


    // 根据支付单生成交易记录
    @Override
    public TradeRecord createPaymentTradeRecord(List<OrderPaymentCost> paymentList, Account loginUser) {
        List<Map<String, Object>> paymentData = new ArrayList<>();
        double totalPayCost = 0.00d;
        List<String> paymentIdList = new ArrayList<>();
        for (OrderPaymentCost paymentOrder : paymentList) {
            paymentIdList.add(paymentOrder.getId());
            totalPayCost = MathUtil.add(totalPayCost, paymentOrder.getPayCost());
            paymentData.add(MapUtil.generate(map -> {
                map.put("paymentNo", paymentOrder.getPrePaymentNo());
                map.put("paymentCost", paymentOrder.getPayCost());
                map.put("transportNo", paymentOrder.getTransportNo());
                map.put("robOrderNo", paymentOrder.getRobOrderNo());
                map.put("goodsOrderNo", paymentOrder.getGoodsOrderNo());
            }));
        }
        // 检查8位数交易编码
        String randomNumCode = StringUtil.getRandomNum(8, str -> {
            QueryWrapper<TradeRecord> queryWrapper = new QueryWrapper<TradeRecord>().eq("trade_code", str);
            Long check = tradeRecordMapper.selectCount(queryWrapper);
            return check > 0;
        });
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setTradeType(TradeRecord.TradeType.payment);
        tradeRecord.setTradeStatus(TradeRecord.TradeStatus.create);
        tradeRecord.setOrderPaymentIds(String.join(",", paymentIdList));
        tradeRecord.setOrderPaymentData(JsonUtil.objectToJson(paymentData));
        tradeRecord.setTmsCapitalDataState(TradeRecord.TmsCapitalDataState.needless);
        if (paymentList.size() > 1) { // 订单数量大于1，判定为打包支付
            tradeRecord.setTransName(String.format("打包支付，共%s条支付单", paymentList.size()));
            tradeRecord.setRemark("支付前务必核对订单数量，支付金额，预支付单号等");
        } else {// 订单数量==1，代表货主直接在APP端支付
            tradeRecord.setTransName("请尽快完成支付");
            tradeRecord.setRemark("支付前务必核对您的支付金额");
        }
        tradeRecord.setMoney(CommonUtil.doubleTwo(totalPayCost));
        tradeRecord.setTradeNo(randomNumCode);
        tradeRecord.setTradeNo(DateTimeUtil.dateNo("TD"));
        tradeRecord.setPlatId(paymentList.get(0).getPlatId());
        tradeRecord.setPlatName(paymentList.get(0).getPlatName());
        tradeRecord.setZonePlatId(paymentList.get(0).getZonePlatId());
        tradeRecord.setZonePlatName(paymentList.get(0).getZonePlatName());
        tradeRecord.setPaymentOrganizeId(paymentList.get(0).getShipperOrganizeId());
        tradeRecord.setPaymentOrganizeName(paymentList.get(0).getShipperOrganizeName());
        tradeRecord.setIncomeOrganizeId(paymentList.get(0).getPlatId());
        tradeRecord.setIncomeOrganizeName(paymentList.get(0).getPlatName());
        tradeRecord.setClosingTime(DateTimeUtil.plusDay(new Date(), 1));
        tradeRecord.setInitiateTime(new Date());
        //获取默认收款账号
        BankCard bankCard = bankCardService.getDefaultBankCardByOrganizeId(tradeRecord.getIncomeOrganizeId());
        if (bankCard == null) throw new BusinessException("平台未设置默认收款账户");
        tradeRecord.setIncomeCapitalAccount(bankCard.getBankAccNo());
        tradeRecordMapper.insert(tradeRecord);
        return tradeRecord;
    }

    @Override
    public TradeRecord createSettlementTradeRecord(List<OrderSettlementCost> settlementList, Account loginUser) {
        List<Map<String, Object>> paymentData = new ArrayList<>();
        double totalPayCost = 0.00d;
        List<String> paymentIdList = new ArrayList<>();
        for (OrderSettlementCost settlementOrder : settlementList) {
            paymentIdList.add(settlementOrder.getId());
            totalPayCost = MathUtil.add(totalPayCost, settlementOrder.getSettlementCost());
            paymentData.add(MapUtil.generate(map -> {
                map.put("paymentNo", settlementOrder.getPrePaymentNo());
                map.put("paymentCost", settlementOrder.getSettlementCost());
                map.put("transportNo", settlementOrder.getTransportNo());
            }));
        }
        // 检查8位数交易编码
        String randomNumCode = StringUtil.getRandomNum(8, str -> {
            QueryWrapper<TradeRecord> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("trade_code", str);
            Long check = tradeRecordMapper.selectCount(queryWrapper);
            return check > 0;
        });
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setTradeType(TradeRecord.TradeType.settlement);
        tradeRecord.setTradeStatus(TradeRecord.TradeStatus.create);
        tradeRecord.setOrderPaymentIds(String.join(",", paymentIdList));
        tradeRecord.setOrderPaymentData(JsonUtil.objectToJson(paymentData));
        tradeRecord.setTmsCapitalDataState(TradeRecord.TmsCapitalDataState.creating);
        tradeRecord.setTransName(String.format("本次共支付%s条结算单", paymentIdList.size()));
        tradeRecord.setRemark("支付前务必核对结算订单数量，支付金额，预支付单号等");
        tradeRecord.setTradeNo(DateTimeUtil.dateNo("TD"));
        tradeRecord.setTradeCode(randomNumCode);
        tradeRecord.setPlatId(settlementList.get(0).getPlatId());
        tradeRecord.setPlatName(settlementList.get(0).getPlatName());
        tradeRecord.setZonePlatId(settlementList.get(0).getZonePlatId());
        tradeRecord.setZonePlatName(settlementList.get(0).getZonePlatName());

        tradeRecord.setTradeCost(CommonUtil.doubleTwo(totalPayCost));
//        //减去运营服务费
//        Double technicalCost = ParamUtil.isSuccess(orderRemote.calculateTechnicalFee(totalPayCost));
//        tradeRecord.setTechnicalFee(CommonUtil.doubleTwo(technicalCost));
        //计算两级运营技术服务费
//        Double platCost = ParamUtil.isSuccess(orderRemote.calculatePlatTechnicalFee(tradeRecord.getPlatId(), technicalCost));
//        tradeRecord.setPlatTechnicalFee(CommonUtil.doubleTwo(platCost));
//        Double zonePlatCost = ParamUtil.isSuccess(orderRemote.calculatePlatTechnicalFee(tradeRecord.getZonePlatId(), technicalCost));
//        tradeRecord.setZoneTechnicalFee(CommonUtil.doubleTwo(zonePlatCost));
        //实际费用
        tradeRecord.setMoney(CommonUtil.doubleTwo(totalPayCost));

        tradeRecord.setPaymentOrganizeId(settlementList.get(0).getPlatId());
        tradeRecord.setPaymentOrganizeName(settlementList.get(0).getPlatName());
        tradeRecord.setIncomeOrganizeId(settlementList.get(0).getTruckerOrganizeId());
        tradeRecord.setIncomeOrganizeName(settlementList.get(0).getTruckerOrganizeName());
        tradeRecord.setInitiateTime(new Date());
        tradeRecord.setClosingTime(DateTimeUtil.plusDay(new Date(), 1));
        //获取默认收款账号
        BankCard bankCard = bankCardService.getDefaultBankCardByOrganizeId(tradeRecord.getIncomeOrganizeId());
        if (bankCard == null) throw new BusinessException("司机未设置默认收款账户");
        tradeRecord.setIncomeCapitalAccount(bankCard.getBankAccNo());
        tradeRecordMapper.insert(tradeRecord);
        return tradeRecord;
    }

    @Override
    public TradeRecord createServicePaymentTradeRecord(List<ServicePaymentCost> servicePaymentList, Account loginUser) {
        List<Map<String, Object>> paymentData = new ArrayList<>();
        double totalPayCost = 0.00d;
        List<String> paymentIdList = new ArrayList<>();
        for (ServicePaymentCost servicePayment : servicePaymentList) {
            paymentIdList.add(servicePayment.getId());
            totalPayCost = MathUtil.add(totalPayCost, servicePayment.getServiceCost());
            paymentData.add(MapUtil.generate(map -> {
                map.put("paymentNo", servicePayment.getPrePaymentNo());
                map.put("paymentCost", servicePayment.getServiceCost());
                map.put("transportNo", servicePayment.getSourceOrderNo());
            }));
        }
        // 检查8位数交易编码
        String randomNumCode = StringUtil.getRandomNum(8, str -> {
            QueryWrapper<TradeRecord> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("trade_code", str);
            Long check = tradeRecordMapper.selectCount(queryWrapper);
            return check > 0;
        });
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setTradeType(TradeRecord.TradeType.service);
        tradeRecord.setTradeStatus(TradeRecord.TradeStatus.create);
        tradeRecord.setOrderPaymentIds(String.join(",", paymentIdList));
        tradeRecord.setOrderPaymentData(JsonUtil.objectToJson(paymentData));
        tradeRecord.setTmsCapitalDataState(TradeRecord.TmsCapitalDataState.creating);
        tradeRecord.setTransName(String.format("本次共支付%s条费用单", paymentIdList.size()));
        tradeRecord.setRemark("支付前务必核对支付金额，预支付单号等");
        tradeRecord.setTradeNo(DateTimeUtil.dateNo("TD"));
        tradeRecord.setTradeCode(randomNumCode);
        tradeRecord.setMoney(CommonUtil.doubleTwo(totalPayCost));

        tradeRecord.setIncomeOrganizeId(servicePaymentList.get(0).getSuperiorPlatId());
        tradeRecord.setIncomeOrganizeName(servicePaymentList.get(0).getSuperiorPlatName());

        tradeRecord.setPaymentOrganizeId(servicePaymentList.get(0).getServicePlatId());
        tradeRecord.setPaymentOrganizeName(servicePaymentList.get(0).getServicePlatName());
        tradeRecord.setInitiateTime(new Date());
        tradeRecord.setClosingTime(DateTimeUtil.plusDay(new Date(), 1));
        //获取默认收款账号
        BankCard bankCard = bankCardService.getDefaultBankCardByOrganizeId(tradeRecord.getIncomeOrganizeId());
        if (bankCard == null) throw new BusinessException("未设置默认收款账户");
        tradeRecord.setIncomeCapitalAccount(bankCard.getBankAccNo());
        tradeRecordMapper.insert(tradeRecord);
        return tradeRecord;
    }
    //

    @Override
    public TradeRecord createRefundTradeRecord(OrderRefundCost orderRefundCost, Account loginUser) {
        List<Map<String, Object>> paymentData = new ArrayList<>();
        double totalPayCost = 0.00d;
        totalPayCost = MathUtil.add(totalPayCost, orderRefundCost.getOriginalPayCost());
        paymentData.add(MapUtil.generate(map -> {
            map.put("paymentNo", orderRefundCost.getPrePaymentNo());
            map.put("paymentCost", orderRefundCost.getRefundCost());
            map.put("transportNo", orderRefundCost.getTradeNo());
        }));
        // 检查8位数交易编码
        String randomNumCode = StringUtil.getRandomNum(8, str -> {
            QueryWrapper<TradeRecord> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("trade_code", str);
            Long check = tradeRecordMapper.selectCount(queryWrapper);
            return check > 0;
        });
        TradeRecord originalTradeRecord = getTradeRecordByTradeNo(orderRefundCost.getOriginalTradeNo());
        ParamUtil.isNull(originalTradeRecord, "获取原交易单失败！");
        if (originalTradeRecord.getTradeStatus() != TradeRecord.TradeStatus.paySuccess)
            throw new BusinessException("原交易单未支付成功");
        TradeRecord tradeRecord = new TradeRecord();
        tradeRecord.setTradeType(TradeRecord.TradeType.refund);
        tradeRecord.setTradeStatus(TradeRecord.TradeStatus.create);
        tradeRecord.setOrderPaymentIds(orderRefundCost.getId());
        tradeRecord.setOrderPaymentData(JsonUtil.objectToJson(paymentData));
        tradeRecord.setTmsCapitalDataState(TradeRecord.TmsCapitalDataState.needless);
        tradeRecord.setTransName("货主发起退款");
        tradeRecord.setRemark("支付前务必核对支付方式，退款金额，预支付单号等");
        tradeRecord.setTradeNo(DateTimeUtil.dateNo("TD"));
        tradeRecord.setTradeCode(randomNumCode);
        tradeRecord.setPayType(orderRefundCost.getRefundType());
        tradeRecord.setMoney(CommonUtil.doubleTwo(totalPayCost));
        tradeRecord.setPlatId(orderRefundCost.getPlatId());
        tradeRecord.setPlatName(orderRefundCost.getPlatName());
        tradeRecord.setZonePlatId(orderRefundCost.getZonePlatId());
        tradeRecord.setZonePlatName(orderRefundCost.getZonePlatName());
        tradeRecord.setPaymentOrganizeId(orderRefundCost.getPlatId());
        tradeRecord.setPaymentOrganizeName(orderRefundCost.getPlatName());
        tradeRecord.setIncomeOrganizeId(orderRefundCost.getShipperOrganizeId());
        tradeRecord.setIncomeOrganizeName(orderRefundCost.getShipperOrganizeName());
        tradeRecord.setBankType(originalTradeRecord.getBankType());
        tradeRecord.setOriginalPaymentOrderId(originalTradeRecord.getId());
        tradeRecord.setPaymentCapitalAccount(originalTradeRecord.getIncomeCapitalAccount());
        tradeRecord.setIncomeCapitalAccount(originalTradeRecord.getIncomeCapitalAccount());
        tradeRecord.setClosingTime(DateTimeUtil.plusDay(new Date(), 1));
        tradeRecord.setVerifyUserId(loginUser.getId());
        tradeRecord.setVerifyUserName(loginUser.getName());
        tradeRecord.setVerifyLockTime(new Date());
        tradeRecordMapper.insert(tradeRecord);
        return tradeRecord;
    }

    @Override
    public ReturnData<Object> noticePaymentResult(String[] tradeRecordIds) {
        // #### 发送通知预支付单结果
        return orderRemote.updateOrderPaymentResult(String.join(",", tradeRecordIds));
    }

    @Override
    public TradeRecord getTradeRecordById(String tradeRecordId) {
        return tradeRecordMapper.selectById(tradeRecordId);
    }

    @Override
    public List<TradeRecord> getTradeRecordListByIds(List<String> tradeRecordIds) {
        return tradeRecordMapper.selectBatchIds(tradeRecordIds);
    }

    @Override
    public List<TradeRecord> getTradeRecordListByTradeNo(List<String> tradeRecordTradeNos) {
        QueryWrapper<TradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("trade_no", tradeRecordTradeNos);
        queryWrapper.eq("is_deleted", 0);
        return tradeRecordMapper.selectList(queryWrapper);
    }

    @Override
    public List<TradeRecord> getTradeRecordListByBatchNo(String batchNo) {
        QueryWrapper<TradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("batch_trade_no", batchNo);
        queryWrapper.eq("is_deleted", 0);
        return tradeRecordMapper.selectList(queryWrapper);
    }

    @Override
    public TradeRecord getTradeRecordByTradeNo(String tradeNo) {
        return tradeRecordMapper.selectOne(new QueryWrapper<TradeRecord>().eq("trade_no", tradeNo));
    }

    @Override
    public TradeRecord queryTradeRecordByPaymentId(String paymentOrderId) {
        return tradeRecordMapper.selectOne(new QueryWrapper<TradeRecord>().like("order_payment_ids", paymentOrderId));
    }

    @Override
    public PageData<TradeRecord> getTradeRecordPage(TradeRecord query, Account loginUser, Integer page, Integer limit) {
        QueryWrapper<TradeRecord> queryWrapper = new QueryWrapper<>();
        if (loginUser.getUserType() != UserType.adminUser && loginUser.getUserType() != UserType.yilinUser) {
            if (loginUser.getUserType() == UserType.zoneUser) {
                queryWrapper.eq("zone_plat_id", loginUser.getOrganizeId());
            } else if (loginUser.getUserType() == UserType.platformUser) {
                queryWrapper.eq("plat_id", loginUser.getOrganizeId());
            } else {
                if (loginUser.getRoleType() == RoleType.manager) {
                    queryWrapper.and(cWrapper -> {
                        cWrapper.eq("payment_organize_id", loginUser.getOrganizeId()).or();
                        cWrapper.eq("income_organize_id", loginUser.getOrganizeId());
                    });
                } else queryWrapper.eq("opt_user_id", loginUser.getId());
            }
        }
        QueryUtil.andQueryWrapper(queryWrapper, query);
        return tradeRecordMapper.selectPage(new PageData<>(page, limit), queryWrapper);
    }

    //收款记录 进账
    @Override
    public PageData<TradeRecord> getIncomeTradeRecordPage(TradeRecord query, Account loginUser, Integer page, Integer limit) {
        QueryWrapper<TradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("income_organize_id", loginUser.getOrganizeId());
        QueryUtil.andQueryWrapper(queryWrapper, query);
        return tradeRecordMapper.selectPage(new PageData<>(page, limit), queryWrapper);
    }

    //付款记录 出账
    @Override
    public PageData<TradeRecord> getPayoutTradeRecordPage(TradeRecord query, Account loginUser, Integer page, Integer limit) {

        QueryWrapper<TradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("payment_organize_id", loginUser.getOrganizeId());
        if (loginUser.getRoleType() != RoleType.manager) {
            queryWrapper.and(qw -> {
                qw.eq("opt_lock", false).or().eq("opt_user_id", loginUser.getId());
            });
        }
        QueryUtil.andQueryWrapper(queryWrapper, query);
        return tradeRecordMapper.selectPage(new PageData<>(page, limit), queryWrapper);
    }

    @Override
    public Map<String, Double> getTradeInoutData(Account loginUser, String startTime, String endTime) {
        return statisticsMapper.getTradeInoutData(loginUser, startTime, endTime);
    }


    @Override
    public List<TradeRecord> getErrorTmsTradeRecord() {
        QueryWrapper<TradeRecord> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("tms_capital_data_state", TradeRecord.TmsCapitalDataState.wait).or().eq("tms_capital_data_state", TradeRecord.TmsCapitalDataState.error);
        return tradeRecordMapper.selectList(queryWrapper);
    }

}
